{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_fowjg6u"
   },
   "source": [
    "## Single File Code\n",
    "\n",
    "In the previous concept, you saw some example code that wouldn't compile because the functions were out of order:\n",
    "```cpp\n",
    "#include <iostream>\n",
    "#include <vector>\n",
    "using std::vector;\n",
    "using std::cout;\n",
    "\n",
    "\n",
    "int IncrementAndComputeVectorSum(vector<int> v) {\n",
    "    int total = 0;\n",
    "    AddOneToEach(v);\n",
    "\n",
    "    for (auto i: v) {\n",
    "        total += i;\n",
    "    }\n",
    "    return total;\n",
    "}\n",
    "\n",
    "void AddOneToEach(vector<int> &v) {\n",
    "    for (auto& i: v) {\n",
    "        i++;\n",
    "    }\n",
    "}\n",
    "\n",
    "int main() {\n",
    "    vector<int> v{1, 2, 3, 4};\n",
    "    int total = IncrementAndComputeVectorSum(v);\n",
    "    cout << \"The total is: \" << total << \"\\n\";\n",
    "}\n",
    "```\n",
    "\n",
    "In the last exercise of the notebook, you were to separate that code into a header `.h` file and a `.cpp` file. But what if you wanted to use completely separate files for each of the functions? For example, you might want to do this if the functions were going to belong to different classes or libraries.\n",
    "\n",
    "## Multi-file Code\n",
    "\n",
    "In the next few cells these functions have been separated into several different files. The structure of the included files is as follows:\n",
    "\n",
    "> `vect_add_one` --> `increment_and_sum` -->`main`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_j97pewx"
   },
   "source": [
    "### `vect_add_one.h` and `vect_add_one.cpp`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "graffitiCellId": "id_8yjy16e"
   },
   "outputs": [],
   "source": [
    "#ifndef VECT_ADD_ONE_H\n",
    "#define VECT_ADD_ONE_H\n",
    "\n",
    "#include <vector>\n",
    "using std::vector;\n",
    "\n",
    "// AddOneToEach method declaration.\n",
    "void AddOneToEach(vector<int> &v);\n",
    "\n",
    "#endif"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "graffitiCellId": "id_kuff4yu"
   },
   "outputs": [],
   "source": [
    "#include \"vect_add_one.h\"\n",
    "\n",
    "void AddOneToEach(vector<int> &v) \n",
    "{\n",
    "    for (auto& i: v) {\n",
    "        i++;\n",
    "    }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_tc91qx8"
   },
   "source": [
    "### `increment_and_sum.h` and `increment_and_sum.cpp`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "graffitiCellId": "id_kmlof40"
   },
   "outputs": [],
   "source": [
    "#ifndef INCREMENT_AND_SUM_H\n",
    "#define INCREMENT_AND_SUM_H\n",
    "\n",
    "#include <vector>\n",
    "using std::vector;\n",
    "\n",
    "// IncrementAndComputeVectorSum method declaration.\n",
    "int IncrementAndComputeVectorSum(vector<int> v);\n",
    "\n",
    "#endif"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "graffitiCellId": "id_u0tdkzu"
   },
   "outputs": [],
   "source": [
    "#include \"vect_add_one.h\"\n",
    "\n",
    "int IncrementAndComputeVectorSum(vector<int> v) {\n",
    "    int total = 0;\n",
    "    AddOneToEach(v);\n",
    "\n",
    "    for (auto i: v) {\n",
    "        total += i;\n",
    "    }\n",
    "    return total;\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_lovfxcx"
   },
   "source": [
    "### `main.cpp`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "graffitiCellId": "id_47n3axl",
    "graffitiConfig": {
     "executeCellViaGraffiti": "xye2k7e_id5rrzk"
    }
   },
   "outputs": [],
   "source": [
    "#include <iostream>\n",
    "#include <vector>\n",
    "#include \"increment_and_sum.h\"\n",
    "using std::vector;\n",
    "using std::cout;\n",
    "\n",
    "int main() \n",
    "{\n",
    "    vector<int> v{1, 2, 3, 4};\n",
    "    int total = IncrementAndComputeVectorSum(v);\n",
    "    cout << \"The total is: \" << total << \"\\n\";\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_xye2k7e"
   },
   "source": [
    "<span class=\"graffiti-highlight graffiti-id_xye2k7e-id_id5rrzk\"><i></i><button>Compile & Execute</button></span> &nbsp; <span class=\"graffiti-highlight graffiti-id_wzpt9nh-id_6u6jxjk\"><i></i><button>See Explanation</button></span>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_wvcrmxo",
    "graffitiConfig": {
     "rows": 6,
     "terminalId": "id_lukab4g",
     "type": "terminal"
    }
   },
   "source": [
    "<i>Loading terminal (id_wvcrmxo), please wait...</i>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_3hpnz36"
   },
   "source": [
    "If you look carefully at the files above, you will see several things:\n",
    "- `vect_add_one.h` is included in `increment_and_sum.cpp`.\n",
    "\n",
    "  >This is becuase `AddOneToEach` is used in `IncrementAndComputeVectorSum`. Including the `vect_add_one.h` header means that the `AddOneToEach` function declaration is pasted into `increment_and_sum.cpp`, so no compiler error will occur when the `AddOneToEach` function is used.\n",
    "  \n",
    "- Only the header file needs to be included in another file. \n",
    "\n",
    "  >As long as the header file is included, the corresponding function declarations will be included. When the compiler finds an undefined function, it has already seen the function's declaration. This means the compiler can continue on without error until it finds the definition of the function, regardless of where that definition is.\n",
    "  \n",
    "- Some libraries, like `<vector>` are included in mutliple files.\n",
    "\n",
    "  >Each file is compiled alone and must have all the declarations and libraries necessary to compile, so the necessary libraries must be included. This is another reason why [include guards](https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rs-guards) are important - if multiple headers were included in `main`, each with the same `#include <vector>` statement, you wouldn't want the `vector` header pasted multiple times into the code.\n",
    "  \n",
    "- The `g++` compile command from the \"Run Code\" button is:\n",
    "\n",
    "  ```bash\n",
    "  g++ -std=c++17 ./code/main.cpp ./code/increment_and_sum.cpp ./code/vect_add_one.cpp && ./a.out\n",
    "  ```\n",
    "\n",
    "  >When compiling, each of the relevant `.cpp` files must be included in the compile command. The `-std=c++17` specifies that we are using the C++ 17 standard (which happens automatically in the terminal)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "graffitiCellId": "id_xuqss6b"
   },
   "source": [
    "### Your Turn!\n",
    "\n",
    "In the course project code, all the files will be set up for you, so you will not need to manually create the header files and write `#include` statments yourself. Nonetheless, it is still helpful to see how this works.\n",
    "\n",
    "Now that you have seen the code split into multiple files, try compiling and running the code yourself from the command line above, instead of relying on the \"Compile & Execute\" button. \n",
    "\n",
    "Remember that you will need to include all the files in your compile command:\n",
    "```bash\n",
    "g++ -std=c++17 ./code/main.cpp ./code/increment_and_sum.cpp ./code/vect_add_one.cpp\n",
    "```\n",
    "followed by\n",
    "```bash\n",
    "./a.out\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "graffiti": {
   "firstAuthorId": "813558546",
   "id": "id_p0q0ziu",
   "language": "EN"
  },
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xeus-cling-cpp17"
  },
  "language_info": {
   "codemirror_mode": "text/x-c++src",
   "file_extension": ".cpp",
   "mimetype": "text/x-c++src",
   "name": "c++",
   "version": "-std=c++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
